package com.music.service.music.impl;

import com.music.dto.music.PlaylistDTO;
import com.music.dto.tag.TagDTO;
import com.music.dto.utils.PagingDTO;
import com.music.dto.utils.TableReqDTO;
import com.music.dto.utils.TableRspDTO;
import com.music.entity.music.PlaylistEntity;
import com.music.mapper.music.PlaylistMapper;
import com.music.service.music.PlaylistService;
import com.music.utils.file.MinioUtil;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
public class PlaylistServiceImpl implements PlaylistService {

    @Resource
    private PlaylistMapper playlistMapper;

    private final MinioUtil minioUtil = MinioUtil.getInstance();

    private final Logger logger = LoggerFactory.getLogger(PlaylistServiceImpl.class);

    @Override
    public TableRspDTO listPlaylistByUserId(Long userId, TableReqDTO tableReqDTO) throws Exception {
        Long count = playlistMapper.countPlaylistByUserId(
                userId,
                tableReqDTO.parseQueryParam("playlistName"));
        List<PlaylistDTO> listPlaylist = playlistMapper.listPlaylistByUserId(
                tableReqDTO.getStart(),
                tableReqDTO.getPageSize(),
                userId,
                tableReqDTO.parseQueryParam("playlistName"));
        List<TagDTO> listAllTag = new ArrayList<>(playlistMapper.listAllTag());
        Map<Long, String> tagMap = new HashMap<>();
        for (TagDTO tagDTO : listAllTag) {
            tagMap.put(tagDTO.getTagId(), tagDTO.getTagName());
        }
        for (PlaylistDTO playlistDTO : listPlaylist) {
            if (StringUtils.isBlank(playlistDTO.getTagId()))
                continue;
            String[] tagIds = playlistDTO.getTagId().split("/");
            List<String> tagNames = new ArrayList<>();
            for (String tagId : tagIds) {
                tagNames.add(tagMap.get(Long.parseLong(tagId)));
            }
            playlistDTO.setTagName(StringUtil.join(tagNames.toArray(), ","));
        }
        PagingDTO pagingDTO = new PagingDTO(
                tableReqDTO.getPageNo(),
                tableReqDTO.getPageSize(),
                count,
                listPlaylist);
        return new TableRspDTO(pagingDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer add(Long userId, PlaylistDTO playlistDTO) throws Exception {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        PlaylistEntity playlistEntity = mapperFactory.getMapperFacade().map(playlistDTO, PlaylistEntity.class);
        playlistEntity.setGmtCreate(new Date());
        playlistEntity.setUserId(userId);
        return playlistMapper.addPlaylist(playlistEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer update(PlaylistDTO playlistDTO) throws Exception {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        PlaylistEntity playlistEntity = mapperFactory.getMapperFacade().map(playlistDTO, PlaylistEntity.class);
        return playlistMapper.updatePlaylist(playlistEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer remove(PlaylistDTO playlistDTO) throws Exception {
        Long playlistId = playlistDTO.getPlaylistId();
        List<String> listAudioUrl = new ArrayList<>(playlistMapper.getAudioUrl(playlistId));
        Integer removeSum = playlistMapper.removePlaylist(playlistId);
        for (String audioUrl : listAudioUrl) {
            minioUtil.remove(audioUrl, "music");
        }
        minioUtil.remove(playlistDTO.getImageUrl(), "image");
        return removeSum;
    }

    @Override
    public TableRspDTO listMusicSquareByUserId(Long userId, TableReqDTO tableReqDTO) throws Exception {
        String tags = tableReqDTO.parseQueryParam("tagIds");
        String[] screeningIds = {};
        Integer sortId = null;
        if (tags != null) {
            screeningIds = tags.split(",");
            for (String id : screeningIds) {
                if (Integer.parseInt(id) < 0) {
                    sortId = Integer.parseInt(id);
                    break;
                }
            }
        }
        int isSelf = Integer.parseInt(tableReqDTO.parseQueryParam("isSelf"));
        if (isSelf == 2) {
            userId = Long.parseLong(tableReqDTO.parseQueryParam("userId"));
        }
        Long count = playlistMapper.countMusicSquareByUserId(userId,
                isSelf,
                tableReqDTO.parseQueryParam("playlistName"));
        List<PlaylistDTO> listPlaylist = playlistMapper.listMusicSquareByUserId(
                isSelf,
                tableReqDTO.parseQueryParam("playlistName"),
                sortId,
                tableReqDTO.getStart(),
                tableReqDTO.getPageSize(),
                userId);
        List<TagDTO> listAllTag = new ArrayList<>(playlistMapper.listAllTag());
        Map<Long, String> tagMap = new HashMap<>();
        for (TagDTO tagDTO : listAllTag) {
            tagMap.put(tagDTO.getTagId(), tagDTO.getTagName());
        }
        for (PlaylistDTO playlistDTO : listPlaylist) {
            if (StringUtils.isBlank(playlistDTO.getTagId()))
                continue;
            String[] tagIds = playlistDTO.getTagId().split("/");
            List<String> tagNames = new ArrayList<>();
            for (String tagId : tagIds) {
                tagNames.add(tagMap.get(Long.parseLong(tagId)));
            }
            playlistDTO.setTagName(StringUtil.join(tagNames.toArray(), ","));
        }
        List<PlaylistDTO> listPlaylistByScreening = new ArrayList<>();
        if (screeningIds.length > 1) {
            boolean isHave;
            for (PlaylistDTO playlistDTO : listPlaylist) {
                isHave = true;
                for (String id : screeningIds) {
                    if (!Arrays.asList(playlistDTO.getTagId().split("/")).contains(id) && Integer.parseInt(id) > 0) {
                        count--;
                        isHave = false;
                    }
                }
                if (isHave)
                    listPlaylistByScreening.add(playlistDTO);
            }
        } else listPlaylistByScreening = listPlaylist;
        PagingDTO pagingDTO = new PagingDTO(
                tableReqDTO.getPageNo(),
                tableReqDTO.getPageSize(),
                count,
                listPlaylistByScreening);
        return new TableRspDTO(pagingDTO);
    }

    @Override
    public Integer getDownloadSum(Long playlistId) throws Exception {
        return playlistMapper.getDownloadSum(playlistId);
    }

    @Override
    public Integer updateTagByPlaylist(Long playlistId, String tagIds) throws Exception {
        return  playlistMapper.updateTagByPlaylist(playlistId, tagIds);
    }
}
